(function (win) {
    function jQuery(dom) {
        return new jQuery.prototype.init(dom)
    }
    jQuery.prototype.init = function (dom) {

    }
    jQuery.prototype.css = function () {

    }
    jQuery.unique = function (arr) {
        var newArr = [];
        var tempObj = {};
        for (var i = 0; i < arr.length; i++) {
            if (!tempObj[arr[i]]) {
                tempObj[arr[i]] = '龌龊兄真浪';
                newArr.push(arr[i]);
            }
        }
        return newArr;
    }
    jQuery.MyCallbacks = function (options) {
        options = options || '';
        var _that = this;
        var list = [];
        var isFire = false;
        var index = 0;
        var args = [];
        var isOne = false;
        function fire() {
            for (; index < list.length; index++) {
                var res = list[index].apply(window, args);
                if (options.indexOf('stopOnFalse') !== -1) {
                    if (res === false) {
                        break
                    }
                }
            }
            if (options.indexOf('once') !== -1) {
                isOne = true;
                list = [];
                index = 0;
            }
        }
        return {
            add: function (fun) {
                list.push(fun);
                if (options.indexOf('unique') !== -1) {
                    list = _that.unique(list);
                }
                if (options.indexOf('memory') !== -1 && isFire) {
                    fire();
                }
            },
            fire: function () {
                if (isOne) return;
                args = arguments;
                index = 0;
                fire();
                isFire = true;
            }
        }
    }
    jQuery.MyDeferred = function () {

        var callBox = [
            [jQuery.MyCallbacks('once memory'), 'done', 'resolve'],
            [jQuery.MyCallbacks('once memory'), 'fail', 'reject'],
            [jQuery.MyCallbacks('memory'), 'progress', 'notify']
        ];
        var flag = true;
        function Deferred() {
            var _that = this;
            for (var i = 0; i < callBox.length; i++) {
                this[callBox[i][1]] = (function (index) {
                    return function (fun) {
                        callBox[index][0].add(fun);
                    }
                })(i);
                this[callBox[i][2]] = (function (index) {
                    return function () {
                        var args = arguments;
                        if (flag) {
                            callBox[index][0].fire.apply(window, args);
                            callBox[index][2] === 'resolve' || callBox[index][2] === 'reject' ? flag = false : '';
                        }
                    }
                })(i);
            }
            this.then = function (onRes, onRej, onNotify) {
                var def = jQuery.MyDeferred();
                callBox[0][0].add(function () {
                    try {
                        var args = arguments;
                        var res = onRes.apply(window, args);
                        handlePro(res, def.resolve, def.reject, def.notify);
                    } catch (err) {
                        def.reject(err);
                    }

                });
                callBox[1][0].add(function () {
                    try {
                        var args = arguments;
                        var res = onRej.apply(window, args);
                        handlePro(res, def.resolve, def.reject, def.notify);
                    } catch (err) {
                        def.reject(err);
                    }

                });
                callBox[2][0].add(function () {
                    try {
                        var args = arguments;
                        var res = onNotify.apply(window, args);
                        handlePro({ key: 'notify', res: res }, def.resolve, def.reject, def.notify);
                    } catch (err) {
                        def.reject(err);
                    }
                });
                return def.promise();
            }
            this.promise = function () {
                var tempDef = jQuery.MyDeferred();
                delete tempDef.resolve;
                delete tempDef.reject;
                delete tempDef.notify;

                tempDef.then = _that.then;
                tempDef.done = _that.done;
                tempDef.fail = _that.fail;
                tempDef.progress = _that.progress;
                return tempDef;
            }
        }
        function handlePro(res, resolve, reject, notify) {
            if (typeof res === 'object' && res.constructor.name === Deferred.name && res.then) {
                res.then(function () {
                    var args = arguments;
                    resolve.apply(window, args);
                }, function () {
                    var args = arguments;
                    reject.apply(window, args);
                }, function () {
                    var args = arguments;
                    notify.apply(window, args);
                })
            } else if (typeof res === 'object' && res.key === 'notify') {
                notify(res);
            } else {
                resolve(res);
            }
        }
        return new Deferred();
    }
    jQuery.prototype.init.prototype = jQuery.prototype;
    win.$ = win.jQuery = jQuery;

})(window);